#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include "StdThread.h"

struct StdThread
{
   pthread_t pid;
};

Thread *ThreadInit(void *(*func)(void *), void *arg) //func：这是一个指向函数的指针，该函数接受一个 void 类型的指针参数并返回一个 void 类型的指针 这是一个 void 类型的指针，用来传递给 func 函数作为参数
{   
    Thread*t = (Thread*)malloc(sizeof(Thread));
    if(t == NULL)
    {
        perror("malloc");
        return NULL;
    }

    pthread_create(&t->pid,NULL,func,arg); //pthread_create 函数来创建一个新的线程 &t->pid 可以将该ID存储到 pid 成员中。NULL：这是一个指向 pthread_attr_t 结构的指针，用于设置线程的属性，通常传入 NULL 表示使用默认属性 func：这是一个指向函数的指针，表示新线程将要执行的函数 arg：这是传递给 func 函数的参数
    return t;
}

void* ThreadJoin(Thread *t)
{   
    void* retval;
    pthread_join(t->pid,NULL); //pthread_join 函数来等待指定线程的结束，并阻塞当前线程直到该线程结束 t->pid：这是要等待的线程的ID NULL：这是一个指向 void* 类型的指针，用于获取线程函数的返回值。在这里传入 NULL 表示不获取线程函数的返回值
    return retval;
}

void ThreadDetach(Thread *t)
{
    pthread_detach(t->pid); // pthread_detach 函数来将指定线程标记为“可分离状态”，使得线程结束后能够自动释放其资源 t->pid：要标记为可分离的线程的ID，t 是一个指向 Thread 结构体的指针，pid 成员存储了线程的ID
}

void ThreadCancel(Thread *t)
{
    pthread_cancel(t->pid); //pthread_cancel 函数来请求取消指定的线程
}

void ClearThread(Thread *t)
{
    free(t);
}



struct StdMutex
{
   pthread_mutex_t mutex;
};

Mutex *MutexInit()
{   
    Mutex * m = (Mutex*)malloc(sizeof(Mutex));
    if(m==NULL)
    {
        printf("mutex malloc error\n");
        return NULL;
    }
    pthread_mutex_init(&m->mutex,NULL); //调用了 pthread_mutex_init 函数来初始化一个互斥锁 &m->mutex 是对 Mutex 结构体中互斥锁成员的地址的引用 NULL 作为第二个参数表示使用默认的互斥锁属性
    return m;
}

void MutexLock(Mutex *m)
{  
     pthread_mutex_lock(&m->mutex); //调用了 pthread_mutex_lock 函数来锁定一个互斥锁
}

void MutexUnlock(Mutex *m)
{
    pthread_mutex_unlock(&m->mutex); //调用了 pthread_mutex_unlock 函数来释放互斥锁 m->mutex
}

bool MutexTryLock(Mutex *m, int seconds, int count)
{   
    while(count != 0)
    {   
        //上锁成功
        if(pthread_mutex_trylock(&m->mutex) == 0) //使用了 pthread_mutex_trylock 函数来尝试获取互斥锁 m->mutex，并且通过检查返回值是否为0来确定是否成功获取了锁
        {
            return true;
        }
        else
        {   

            sleep(seconds);
            count--;
        }
    }
    return false;
}

void ClearMutex(Mutex *m)
{
    pthread_mutex_destroy(&m->mutex); //调用了 pthread_mutex_destroy 函数来销毁互斥锁 m->mutex
    free(m);
}



struct StdConditionVar
{
    pthread_cond_t cond;
};

Cond *CondInit()
{   
    Cond * c = (Cond*)malloc(sizeof(Cond));
    if(c == NULL)
    {
        printf("Cond malloc error!\n");
        return NULL;
    }

    pthread_cond_init(&c->cond,NULL); //pthread_cond_init 函数来初始化条件变量 c->cond &c->cond 是对 Cond 结构体中条件变量成员的地址的引用
    return c;
}

void CondWait(Cond *c, Mutex *m)
{   
    //阻塞线程等待条件变量信号，放开锁
    pthread_cond_wait(&c->cond,&m->mutex); //调用了 pthread_cond_wait 函数，用于在条件变量 c->cond 上等待，并且在等待期间会释放互斥锁 m->mutex
}

void CondSignal(Cond *c)
{
    pthread_cond_signal(&c->cond); //调用了 pthread_cond_signal 函数来发送信号给条件变量 c->cond
}

void CondBroadcast(Cond *c)
{
    pthread_cond_broadcast(&c->cond); //这行代码调用了 pthread_cond_broadcast 函数来广播信号给条件变量 c->cond 上的所有等待线程
}

void ClearCond(Cond *c)
{
    pthread_cond_destroy(&c->cond); //调用了 pthread_cond_destroy 函数来销毁条件变量 c->cond
    free(c);
}

struct StdRWMutex
{
    Mutex *m;
    Cond *readCond;
    Cond *writeCond;
    int writers; //写的线程数量
    int readers; //读的线程数量
    int waitWriters; //等待要写的线程数量
};

RWMutex *RWMutexInit()
{   
    RWMutex *rw = (RWMutex*)malloc(sizeof(RWMutex));
    if(rw == NULL)
    {
        printf("RWMutexInit malloc error!\n");
        return NULL;
    }
    rw->m = MutexInit();
    rw->readCond = CondInit();
    rw->writeCond = CondInit();
    rw->readers = rw->writers = rw->waitWriters = 0;
    return rw;
}

void RwReadLock(RWMutex *rw)
{
    MutexLock(rw->m);
    while(rw->writers > 0||rw->waitWriters > 0)
    {
        CondWait(rw->readCond,rw->m);
    }
    rw->readers++;
    MutexUnlock(rw->m);
}

void RWReadUnlock(RWMutex * rw)
{
    MutexLock(rw->m);
    rw->readers--;
    if(rw->readers == 0)
    {
        CondSignal(rw->writeCond); //通知一个等待在该条件变量上的线程，告诉它可以继续执行了
    }
    MutexUnlock(rw->m);
}

void RWWritelock(RWMutex *rw)
{ 
    MutexLock(rw->m);
    rw->waitWriters++;
    while(rw->readers > 0 || rw->writers > 0)
    {
        CondWait(rw->writeCond,rw->m);
    }
    rw->waitWriters--;
    rw->writers++;

    MutexUnlock(rw->m);

}

void RWWriteUnlock(RWMutex *rw)
{
    MutexLock(rw->m);
    rw->writers--;
    if(rw->waitWriters > 0)
    {
        CondSignal(rw->writeCond);
    }
    else
    {
        CondBroadcast(rw->readCond);
    }

    MutexUnlock(rw->m);
}

void ClearRwMutex(RWMutex *rw)
{
    ClearMutex(rw->m);
    ClearCond(rw->readCond);
    ClearCond(rw->writeCond);
    free(rw);
}
